<?php

/*
 *      This is NOT a freeware, use is subject to license terms
 *      [SEOPHP] (C) 2012-2015 QQ:224505576  SITE: http://seophp.taobao.com/
*/

error_reporting(E_ERROR | E_WARNING | E_PARSE);
@set_time_limit(1000);
@set_magic_quotes_runtime(0);

define('IN_SEOPHP', TRUE);
define('ROOT_PATH', dirname(__FILE__).'/../');

require ROOT_PATH.'./App/Conf/seophp_version.php';
require ROOT_PATH.'./install/include/install_var.php';
require ROOT_PATH.'./install/include/install_mysql.php';
require ROOT_PATH.'./App/Common/common.php';
require ROOT_PATH.'./install/include/install_function.php';
require ROOT_PATH.'./install/include/install_lang.php';

$view_off = getgpc('view_off');

define('VIEW_OFF', $view_off ? TRUE : FALSE);

$allow_method = array('show_license', 'env_check', 'db_init', 'ext_info', 'install_check', 'tablepre_check', 'uninstall', 'update');
$not_in_method = array('ext_info', 'uninstall', 'update');

$step = intval(getgpc('step', 'R')) ? intval(getgpc('step', 'R')) : 0;
$method = getgpc('method');

if(empty($method) || !in_array($method, $allow_method)) {
	$method = isset($allow_method[$step]) ? $allow_method[$step] : '';
}

if(empty($method)) {
	show_msg('method_undefined', $method, 0);
}

if(file_exists($lockfile) && !in_array($method, $not_in_method)) {
	show_uninstall();
	//show_msg('install_locked', '', 0);
} elseif(!class_exists('dbstuff')) {
	show_msg('database_nonexistence', '', 0);
}

timezone_set();

if($method == 'show_license') {
	show_license();

} elseif($method == 'env_check') {

	VIEW_OFF && function_check($func_items);

	env_check($env_items);

	dirfile_check($dirfile_items);

	show_env_result($env_items, $dirfile_items, $func_items, $filesock_items);

} elseif($method == 'db_init') {

	$submit = true;

	$default_config = $_config = array();
	$default_configfile = './App/Conf/config_default.php';

	if(!file_exists(ROOT_PATH.$default_configfile)) {
		exit('config_default.php was lost, please reupload this  file.');
	} else {
		$_config = include(ROOT_PATH.$default_configfile);
		$default_config = $_config;
	}

	if(file_exists(ROOT_PATH.CONFIG)) {
		include ROOT_PATH.CONFIG;
	} else {
		$_config = $default_config;
	}

	$dbhost = $_config['DB_HOST'];
	$dbname = $_config['DB_NAME'];
	$dbpw = $_config['DB_PWD'];
	$dbuser = $_config['DB_USER'];
	$tablepre = $_config['DB_PREFIX'];

	$adminemail = 'admin@admin.com';

	$error_msg = array();
	if(isset($form_db_init_items) && is_array($form_db_init_items)) {
		foreach($form_db_init_items as $key => $items) {
			$$key = getgpc($key, 'p');
			if(!isset($$key) || !is_array($$key)) {
				$submit = false;
				break;
			}
			foreach($items as $k => $v) {
				$tmp = $$key;
				$$k = $tmp[$k];
				if(empty($$k) || !preg_match($v['reg'], $$k)) {
					if(empty($$k) && !$v['required']) {
						continue;
					}
					$submit = false;
					VIEW_OFF or $error_msg[$key][$k] = 1;
				}
			}
		}
	} else {
		$submit = false;
	}

	if($submit && !VIEW_OFF && $_SERVER['REQUEST_METHOD'] == 'POST') {
		if($password != $password2) {
			$error_msg['admininfo']['password2'] = 1;
			$submit = false;
		}
		$forceinstall = isset($_POST['dbinfo']['forceinstall']) ? $_POST['dbinfo']['forceinstall'] : '';
		$dbname_not_exists = true;
		if(!empty($dbhost) && empty($forceinstall)) {
			$dbname_not_exists = check_db($dbhost, $dbuser, $dbpw, $dbname, $tablepre);
			if(!$dbname_not_exists) {
				$form_db_init_items['dbinfo']['forceinstall'] = array('type' => 'checkbox', 'required' => 0, 'reg' => '/^.*+/');
				$error_msg['dbinfo']['forceinstall'] = 1;
				$submit = false;
				$dbname_not_exists = false;
			}
		}
	}

	if($submit) {

		$step = $step + 1;
		if(empty($dbname)) {
			show_msg('dbname_invalid', $dbname, 0);
		} else {
			$link = @mysql_connect($dbhost, $dbuser, $dbpw);
			if(!$link) {
				$errno = mysql_errno($link);
				$error = mysql_error($link);
				if($errno == 1045) {
					show_msg('database_errno_1045', $error, 0);
				} elseif($errno == 2003) {
					show_msg('database_errno_2003', $error, 0);
				} else {
					show_msg('database_connect_error', $error, 0);
				}
			}

			if(mysql_get_server_info() > '4.1') {
				mysql_query("CREATE DATABASE IF NOT EXISTS `$dbname` DEFAULT CHARACTER SET ".DBCHARSET, $link);
			} else {
				mysql_query("CREATE DATABASE IF NOT EXISTS `$dbname`", $link);
			}

			if(mysql_errno()) {
				show_msg('database_errno_1044', mysql_error(), 0);
			}
			mysql_close($link);
		}

		if(strpos($tablepre, '.') !== false || intval($tablepre{0})) {
			show_msg('tablepre_invalid', $tablepre, 0);
		}

		if($username && $email && $password) {
			if(strlen($username) > 15 || preg_match("/^$|^c:\\con\\con$|　|[,\"\s\t\<\>&]|^Guest/is", $username)) {
				show_msg('admin_username_invalid', $username, 0);
			} elseif(!strstr($email, '@') || $email != stripslashes($email) || $email != dhtmlspecialchars($email)) {
				show_msg('admin_email_invalid', $email, 0);
			}
		} else {
			show_msg('admininfo_invalid', '', 0);
		}

		$seophpkey = substr(md5($_SERVER['SERVER_ADDR'].$_SERVER['HTTP_USER_AGENT'].$dbhost.$dbuser.$dbpw.$dbname.$username.$password.$pconnect.substr($timestamp, 0, 6)), 8, 6).random(10);
	  $_config['SEOPHP_KEY'] = $seophpkey;
	  $_config['DB_HOST'] = $dbhost;
	  $_config['DB_NAME'] = $dbname;
	  $_config['DB_PWD'] = $dbpw;
	  $_config['DB_USER'] = $dbuser;
	  $_config['DB_PREFIX'] = $tablepre;
		$_config['COOKIE_PREFIX'] = random(4).'_';


		save_config_file(ROOT_PATH.CONFIG, $_config, $default_config);

		$db = new dbstuff;

		$db->connect($dbhost, $dbuser, $dbpw, $dbname, DBCHARSET);

		if(!VIEW_OFF) {
			show_header();
			show_install();
		}

		$sql = file_get_contents($sqlfile);
		$sql = str_replace("\r\n", "\n", $sql);
		runquery($sql);
		
		$install_data_sql = ROOT_PATH.'./install/data/install_data.sql';
		if(file_exists($install_data_sql)){
				$sql = file_get_contents(ROOT_PATH.'./install/data/install_data.sql');
				$sql = str_replace("\r\n", "\n", $sql);
				runquery($sql);
		}
		$onlineip = $_SERVER['REMOTE_ADDR'];
		$timestamp = time();

		$password = md5($password);
		$uid = 1;
		$db->query("INSERT INTO {$tablepre}user (id, account, password, email, create_time, update_time, status) VALUES ('$uid', '$username', '$password', '$email', '".time()."', '".time()."', 1);");

		$testdata = $portalstatus = 0;
		$groupstatus = $homestatus = 0;

		if($testdata) {
			install_testdata($username, $uid);
		}
				
		/*
		foreach($serialize_sql_setting as $k => $v) {
			$v = addslashes(serialize($v));
			$db->query("REPLACE INTO {$tablepre}config VALUES ('$k', '$v')");
		}
		*/

		touch($lockfile);
		VIEW_OFF && show_msg('initdbresult_succ');

		if(!VIEW_OFF) {
			echo '<script type="text/javascript">function setlaststep() {document.getElementById("laststep").disabled=false;window.location=\'index.php?method=ext_info\';}</script><script type="text/javascript">setTimeout(function(){window.location=\'index.php?method=ext_info\'}, 0);</script>'."\r\n";
			show_footer();
		}

	}
	if(VIEW_OFF) {

		show_msg('missing_parameter', '', 0);

	} else {
		show_form($form_db_init_items, $error_msg);

	}

} elseif($method == 'ext_info') {
	@touch($lockfile);
	if(VIEW_OFF){
		show_msg('ext_info_succ');
	}else{
		show_header();
		echo '</div><div class="main" style="margin-top: -123px; padding-bottom: 20px;"><ul style="line-height: 200%; margin-left: 30px;">';
		echo '<div id="platformIntro">'.lang('install_end').'</div>';
		echo '</ul></div>';
		show_footer();
	}

} elseif($method == 'install_check') {
	if(file_exists($lockfile)) {
		show_msg('installstate_succ');
	} else {
		show_msg('lock_file_not_touch', $lockfile, 0);
	}
} elseif($method == 'tablepre_check') {
	$dbinfo = getgpc('dbinfo');
	extract($dbinfo);
	if(check_db($dbhost, $dbuser, $dbpw, $dbname, $tablepre)) {
		show_msg('tablepre_not_exists', 0);
	} else {
		show_msg('tablepre_exists', $tablepre, 0);
	}
} elseif($method == 'uninstall') {
	$configfile = './App/Conf/config.php';
	if(!file_exists(ROOT_PATH.$configfile)) {
		exit('config.php was lost, please reupload this  file.');
	}else{
		$_config = include(ROOT_PATH.$configfile);
	}
	
	$dbhost = $_config['DB_HOST'];
	$dbname = $_config['DB_NAME'];
	$dbpw = $_config['DB_PWD'];
	$dbuser = $_config['DB_USER'];

	$db = new dbstuff;

	$db->connect($dbhost, $dbuser, $dbpw, $dbname, DBCHARSET);
	
	if(!VIEW_OFF) {
		show_header();
	}

	$sql = implode('', file($sqlfile));
	preg_match_all("/CREATE\s+TABLE.+?pre\_(.+?)`\s*\((.+?)\)\s*(ENGINE|TYPE)\s*\=/is", $sql, $matches);
	$dropsql = '';
	foreach($matches[1] as $key => $val){
		$dropsql .= 'DROP TABLE IF EXISTS `'.$_config['DB_PREFIX'].$val.'`;';
	}
	runquery($dropsql);
	unlink($lockfile);
	
	echo '</div><div class="main" style="margin-top: -123px; padding-bottom: 20px;"><ul style="line-height: 200%; margin-left: 30px;">';
	echo '<div id="platformIntro">'.lang('uninstall_end').'</div>';
	echo '</ul></div>';	
	
	if(!VIEW_OFF) {
		show_footer();
	}
			
} elseif($method == 'update') {
	$configfile = './App/Conf/config.php';
	if(!file_exists(ROOT_PATH.$configfile)) {
		exit('config.php was lost, please reupload this  file.');
	}else{
		$_config = include(ROOT_PATH.$configfile);
	}
	
	$dbhost = $_config['DB_HOST'];
	$dbname = $_config['DB_NAME'];
	$dbpw = $_config['DB_PWD'];
	$dbuser = $_config['DB_USER'];
	$dbpre = $_config['DB_PREFIX'];

	$db = new dbstuff;

	$db->connect($dbhost, $dbuser, $dbpw, $dbname, DBCHARSET);	

	$sql = implode('', file($sqlfile));
	preg_match_all("/CREATE\s+TABLE.+?pre\_(.+?)`\s*\((.+?)\)\s*(ENGINE|TYPE)\s*\=/is", $sql, $matches);
	$newtables = empty($matches[1])?array():$matches[1];
	$newsqls = empty($matches[0])?array():$matches[0];
	
	echo '</div><div class="main" style="margin-top: -123px; padding-bottom: 20px;"><ul style="line-height: 200%; margin-left: 30px; height: 300px;">';
	echo '<div id="platformIntro">';
	
	$i = empty($_GET['i'])?0:intval($_GET['i']);
	$count_i = count($newtables);
	if($i>=$count_i) {
		show_msg_update('数据库结构升级完毕，进入下一步数据升级操作', $theurl.'?step=ext_info');
	}
	$newtable = $newtables[$i];

	$specid = intval($_GET['specid']);
	if($specid && in_array($newtable, array('forum_post', 'forum_thread'))) {
		$spectable = $newtable;
		$newtable = get_special_table_by_num($newtable, $specid);
	}

	$newcols = getcolumn($newsqls[$i]);

	if(!$query = $db->query("SHOW CREATE TABLE ".$dbpre.$newtable, 'SILENT')) {
		preg_match("/(CREATE TABLE .+?)\s*(ENGINE|TYPE)\s*\=/is", $newsqls[$i], $maths);

		if(strpos($newtable, 'common_session')) {
			$type = mysql_get_server_info() > '4.1' ? " ENGINE=MEMORY".(empty($config['dbcharset'])?'':" DEFAULT CHARSET=$config[dbcharset]" ): " TYPE=HEAP";
		} else {
			$type = mysql_get_server_info() > '4.1' ? " ENGINE=MYISAM".(empty($config['dbcharset'])?'':" DEFAULT CHARSET=$config[dbcharset]" ): " TYPE=MYISAM";
		}
		$usql = $maths[1].$type;

		$usql = str_replace("CREATE TABLE IF NOT EXISTS pre_", 'CREATE TABLE IF NOT EXISTS '.$dbpre, $usql);
		$usql = str_replace("CREATE TABLE IF NOT EXISTS `pre_", 'CREATE TABLE IF NOT EXISTS `'.$dbpre, $usql);
		$usql = str_replace("CREATE TABLE pre_", 'CREATE TABLE '.$dbpre, $usql);
		$usql = str_replace("CREATE TABLE `pre_", 'CREATE TABLE `'.$dbpre, $usql);
		if(!$db->query($usql, 'SILENT')) {
			show_msg_update('添加表 '.$dbpre.$newtable.' 出错,请手工执行以下SQL语句后,再重新运行本升级程序:<br><br>'.dhtmlspecialchars($usql));
		} else {
			$msg = '添加表 '.$dbpre.$newtable.' 完成';
		}
	} else {
		$value = $db->fetch_array($query);
		$oldcols = getcolumn($value['Create Table']);

		$updates = array();
		foreach ($newcols as $key => $value) {
			if($key == 'PRIMARY') {
				if($value != $oldcols[$key]) {
					if(!empty($oldcols[$key])) {
						$usql = "RENAME TABLE ".$dbpre.$newtable." TO ".$db->table($newtable.'_bak');
						if(!$db->query($usql, 'SILENT')) {
							show_msg_update('升级表 '.$dbpre.$newtable.' 出错,请手工执行以下升级语句后,再重新运行本升级程序:<br><br><b>升级SQL语句</b>:<div style=\"position:absolute;font-size:11px;font-family:verdana,arial;background:#EBEBEB;padding:0.5em;\">'.dhtmlspecialchars($usql)."</div><br><b>Error</b>: ".$db->error()."<br><b>Errno.</b>: ".$db->errno());
						} else {
							$msg = '表改名 '.$dbpre.$newtable.' 完成！';
							show_msg_update($msg, $theurl.'?method=update&i='.$_GET['i']);
						}
					}
					$updates[] = "ADD PRIMARY KEY $value";
				}
			} elseif ($key == 'KEY') {
				foreach ($value as $subkey => $subvalue) {
					if(!empty($oldcols['KEY'][$subkey])) {
						if($subvalue != $oldcols['KEY'][$subkey]) {
							$updates[] = "DROP INDEX `$subkey`";
							$updates[] = "ADD INDEX `$subkey` $subvalue";
						}
					} else {
						$updates[] = "ADD INDEX `$subkey` $subvalue";
					}
				}
			} elseif ($key == 'UNIQUE') {
				foreach ($value as $subkey => $subvalue) {
					if(!empty($oldcols['UNIQUE'][$subkey])) {
						if($subvalue != $oldcols['UNIQUE'][$subkey]) {
							$updates[] = "DROP INDEX `$subkey`";
							$updates[] = "ADD UNIQUE INDEX `$subkey` $subvalue";
						}
					} else {
						$usql = "ALTER TABLE  ".$dbpre.$newtable." DROP INDEX `$subkey`";
						$db->query($usql, 'SILENT');
						$updates[] = "ADD UNIQUE INDEX `$subkey` $subvalue";
					}
				}
			} else {
				if(!empty($oldcols[$key])) {
					if(strtolower($value) != strtolower($oldcols[$key])) {
						$updates[] = "CHANGE `$key` `$key` $value";
					}
				} else {
					$updates[] = "ADD `$key` $value";
				}
			}
		}

		if(!empty($updates)) {
			$usql = "ALTER TABLE ".$dbpre.$newtable." ".implode(', ', $updates);
			if(!$db->query($usql, 'SILENT')) {
				show_msg_update('升级表 '.$dbpre.$newtable.' 出错,请手工执行以下升级语句后,再重新运行本升级程序:<br><br><b>升级SQL语句</b>:<div style=\"position:absolute;font-size:11px;font-family:verdana,arial;background:#EBEBEB;padding:0.5em;\">'.dhtmlspecialchars($usql)."</div><br><b>Error</b>: ".$db->error()."<br><b>Errno.</b>: ".$db->errno());
			} else {
				$msg = '升级表 '.$dbpre.$newtable.' 完成！';
			}
		} else {
			$msg = '检查表 '.$dbpre.$newtable.' 完成，不需升级，跳过';
		}
	}

	if($specid) {
		$newtable = $spectable;
	}

	if(get_special_table_by_num($newtable, $specid+1)) {
		$next = $theurl . '?method=update&i='.($_GET['i']).'&specid='.($specid + 1);
	} else {
		$next = $theurl.'?method=update&i='.($_GET['i']+1);
	}
	show_msg_update("[ $i / $count_i ] ".$msg, $next);
	
	echo '</div></ul></div>';
		
}








function has_another_special_table($tablename, $key) {
	if(!$key) {
		return $tablename;
	}

	$tables_array = get_special_tables_array($tablename);

	if($key > count($tables_array)) {
		return FALSE;
	} else {
		return TRUE;
	}
}

function get_special_tables_array($tablename) {
	global $db, $dbpre;
	$tablename = $dbpre.$tablename;
	$tablename = str_replace('_', '\_', $tablename);
	$query = $db->query("SHOW TABLES LIKE '{$tablename}\_%'");
	//$dbo = $db;
	$tables_array = array();
	while($row = $db->fetch_array($query, MYSQL_NUM)) {
		if(preg_match("/^{$tablename}_(\\d+)$/i", $row[0])) {
			$prefix_len = strlen($dbpre);
			$row[0] = substr($row[0], $prefix_len);
			$tables_array[] = $row[0];
		}
	}
	return $tables_array;
}

function get_special_table_by_num($tablename, $num) {
	$tables_array = get_special_tables_array($tablename);

	$num --;
	return isset($tables_array[$num]) ? $tables_array[$num] : FALSE;
}

function getcolumn($creatsql) {

	$creatsql = preg_replace("/ COMMENT '.*?'/i", '', $creatsql);
	preg_match("/\((.+)\)\s*(ENGINE|TYPE)\s*\=/is", $creatsql, $matchs);

	$cols = explode("\n", $matchs[1]);
	$newcols = array();
	foreach ($cols as $value) {
		$value = trim($value);
		if(empty($value)) continue;
		$value = remakesql($value);
		if(substr($value, -1) == ',') $value = substr($value, 0, -1);

		$vs = explode(' ', $value);
		$cname = $vs[0];

		if($cname == 'KEY' || $cname == 'INDEX' || $cname == 'UNIQUE') {

			$name_length = strlen($cname);
			if($cname == 'UNIQUE') $name_length = $name_length + 4;

			$subvalue = trim(substr($value, $name_length));
			$subvs = explode(' ', $subvalue);
			$subcname = $subvs[0];
			$newcols[$cname][$subcname] = trim(substr($value, ($name_length+2+strlen($subcname))));

		}  elseif($cname == 'PRIMARY') {

			$newcols[$cname] = trim(substr($value, 11));

		}  else {

			$newcols[$cname] = trim(substr($value, strlen($cname)));
		}
	}
	return $newcols;
}

function remakesql($value) {
	$value = trim(preg_replace("/\s+/", ' ', $value));
	$value = str_replace(array('`',', ', ' ,', '( ' ,' )'), array('', ',', ',','(',')'), $value);
	return $value;
}

function show_msg_update($message, $url_forward='') {

	if($url_forward) {
		$message = "<a href=\"$url_forward\">$message (跳转中...)</a><script>setTimeout(\"window.location.href ='$url_forward';\", 1);</script>";
	}

	show_header();
	print<<<END
	</div><div class="main" style="margin-top: -123px; padding-bottom: 20px;"><ul style="line-height: 200%; margin-left: 30px;">;
	<div id="platformIntro">$message</div>;
	</ul></div>;
END;
	show_footer();
	exit();
}